package com.app.web.utils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Date Utility Class used to convert Strings to Dates and Timestamps
 * 
 * to correct time pattern. Minutes should be mm not MM (MM is month).
 */
public class DateUtil
{
    private static Log log = LogFactory.getLog(DateUtil.class);
    private static final String TIME_PATTERN = "HH:mm";
    /*
     * styles of date format
     */
    private static final String DATE_FORMAT_STRING1 = "yyyy-MM-dd";
    private static final String DATE_FORMAT_STRING2 = "yyyy/MM/dd";
    private static final String DATE_FORMAT_STRING3 = "yyyy年MM月dd日";
    private static final String DATE_FORMAT_STRING4 = "yyyyMMdd";

    private static final String DATE_TIME_FORMAT_STRING1 = "yyyy-MM-dd HH:mm:ss";
    private static final String DATE_TIME_FORMAT_STRING2 = "yyyy/MM/dd HH:mm:ss";
    private static final String DATE_TIME_FORMAT_STRING3 = "yyyy年MM月dd日 HH时mm分ss秒";
    private static final String DATE_TIME_FORMAT_STRING4 = "yyyyMMddHHmmss";

    private static final String YEAR_FORMAT_STRING = "yyyy";
    private static final String TIME_FORMAT_STRING1 = "HH:mm:ss";
    private static final String TIME_FORMAT_STRING2 = "HH时mm分ss秒";

    /**
     * 
     * @param yearFormat
     * @param date
     * @return
     */
    private static String getYearString(String yearFormat, Date date)
    {
        SimpleDateFormat format = new SimpleDateFormat(yearFormat);
        return format.format(date);
    }

    /**
     * 
     * @param dateFormat
     * @param date
     * @return
     */
    private static String getDateString(String dateFormat, Date date)
    {
        SimpleDateFormat format = new SimpleDateFormat(dateFormat);
        return format.format(date);
    }

    /**
     * 
     * @param dateTimeFormat
     * @param date
     * @return
     */
    private static String getDateTimeString(String dateTimeFormat, Date date)
    {
        SimpleDateFormat format = new SimpleDateFormat(dateTimeFormat);
        return format.format(date);
    }

    /**
     * 
     * @param timeFormat
     * @param date
     * @return
     */
    private static String getTimeString(String timeFormat, Date date)
    {
        SimpleDateFormat format = new SimpleDateFormat(timeFormat);
        return format.format(date);
    }

    /**
     * 
     * @param dateFormat
     * @param date
     * @return
     * @throws ParseException
     */
    private static Date parseDate(String dateFormat, String date)
            throws ParseException
    {
        SimpleDateFormat format = new SimpleDateFormat(dateFormat);
        return format.parse(date);
    }

    /**
     * 
     * @param dateTimeFormat
     * @param date
     * @return
     * @throws ParseException
     */
    private static Date parseDateTime(String dateTimeFormat, String date)
            throws ParseException
    {
        SimpleDateFormat format = new SimpleDateFormat(dateTimeFormat);
        return format.parse(date);
    }

    /**
     * 
     * @param timeFormat
     * @param date
     * @return
     * @throws ParseException
     */
    private static Date parseTime(String timeFormat, String date)
            throws ParseException
    {
        SimpleDateFormat format = new SimpleDateFormat(timeFormat);
        return format.parse(date);
    }

    /*
     * list the interface to outside
     */

    /**
     * get date string of the input date "yyyy-MM-dd"
     * 
     * @param date Date
     * @return String
     */
    public static String getDateString1(Date date)
    {
        return getDateString(DATE_FORMAT_STRING1, date);
    }

    /**
     * get date string of the input date "yyyy/MM/dd"
     * 
     * @param date
     * @return
     */
    public static String getDateString2(Date date)
    {
        return getDateString(DATE_FORMAT_STRING2, date);
    }

    /**
     * Get date string of the Chinese style "yyyy年MM月dd日".
     * 
     * @param date
     * @return
     */
    public static String getDateStringCN(Date date)
    {
        return getDateString(DATE_FORMAT_STRING3, date);
    }

    /**
     * Get date string of the compact style "yyyyMMdd".
     * 
     * @param date
     * @return
     */
    public static String getDateStringCompact(Date date)
    {
        return getDateString(DATE_FORMAT_STRING4, date);
    }

    /**
     * get date time string of the style "yyyy-MM-dd HH:mm:ss"
     * 
     * @param date Date
     * @return String
     */
    public static String getDateTimeString1(Date date)
    {
        return getDateTimeString(DATE_TIME_FORMAT_STRING1, date);
    }

    /**
     * get date time string of the style "yyyy/MM/dd HH:mm:ss"
     * 
     * @param date
     * @return
     */
    public static String getDateTimeString2(Date date)
    {
        return getDateTimeString(DATE_TIME_FORMAT_STRING2, date);
    }

   
    
    /**
     * Get date string of the Chinese style "yyyy年MM月dd日 HH时mm分ss秒".
     * 
     * @param date
     * @return
     */
    public static String getDateTimeStringCN(Date date)
    {
        return getDateTimeString(DATE_TIME_FORMAT_STRING3, date);
    }

    /**
     * get time string of the style "HH:mm:ss"
     * 
     * @param date
     * @return
     */
    public static String getTimeString(Date date)
    {
        return getTimeString(TIME_FORMAT_STRING1, date);
    }

    /**
     * get time string of the style "HH时mm分ss秒"
     * 
     * @param date
     * @return
     */
    public static String getTimeStringCN(Date date)
    {
        return getTimeString(TIME_FORMAT_STRING2, date);
    }

    /**
     * Get the year string of the style "yyyy"
     * 
     * @param date
     * @return
     */
    public static String getYearString(Date date)
    {
        return getYearString(YEAR_FORMAT_STRING, date);
    }

    /**
     * Get date from string style of "yyyy-MM-dd"
     * 
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date getParseDate1(String date) throws ParseException
    {
        return parseDate(DATE_FORMAT_STRING1, date);
    }
    
    /**
     * Get date from string style of "yyyy-MM-dd HH:mm:ss"
     * 
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date getParseDate3(String date) throws ParseException
    {
        return parseDate(DATE_TIME_FORMAT_STRING1, date);
    }
    
    /**
     * Get date from string style of "yyyyMMddHHmmss"
     * 
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date getParseDate4(String date) throws ParseException
    {
        return parseDate(DATE_TIME_FORMAT_STRING4, date);
    }

    /**
     * Get date from string style of "yyyy/MM/dd"
     * 
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date getParseDate2(String date) throws ParseException
    {
        return parseDate(DATE_FORMAT_STRING2, date);
    }

    /**
     * Get the year of the input date.
     * 
     * @param s
     * @return
     * @throws ParseException
     */
    public static int getYearOfDate(Date date) throws ParseException
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String d = format.format(date);
        return Integer.parseInt(d.substring(0, 4));
    }

    /**
     * Get the month of the input date
     * 
     * @param s
     * @return
     * @throws ParseException
     */
    public static int getMonthOfDate(Date date) throws ParseException
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String d = format.format(date);
        return Integer.parseInt(d.substring(5, 7));
    }

    /**
     * Get the day of the input date.
     * 
     * @param s
     * @return
     * @throws ParseException
     */
    public static int getDayOfDate(Date date) throws ParseException
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String d = format.format(date);
        return Integer.parseInt(d.substring(8, 10));
    }

    /**
     * Get first day of the month.
     * 
     * @param year
     * @param month
     * @return
     * @throws ParseException
     */
    public static Date getFirstDay(String year, String month)
            throws ParseException
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.parse(year + "-" + month + "-1");
    }

    /**
     * Get first day of the month.
     * 
     * @param year
     * @param month
     * @return
     * @throws ParseException
     */
    public static Date getFirstDay(int year, int month) throws ParseException
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.parse(year + "-" + month + "-1");
    }

    /**
     * Get the last day of the month.
     * 
     * @param year
     * @param month
     * @return
     * @throws ParseException
     */
    public static Date getLastDay(String year, String month)
            throws ParseException
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = format.parse(year + "-" + month + "-1");

        Calendar scalendar = new GregorianCalendar();
        scalendar.setTime(date);
        scalendar.add(Calendar.MONTH, 1);
        scalendar.add(Calendar.DATE, -1);
        date = scalendar.getTime();
        return date;
    }

    /**
     * Get the last day of the month.
     * 
     * @param year
     * @param month
     * @return
     * @throws ParseException
     */
    public static Date getLastDay(int year, int month) throws ParseException
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = format.parse(year + "-" + month + "-1");

        Calendar scalendar = new GregorianCalendar();
        scalendar.setTime(date);
        scalendar.add(Calendar.MONTH, 1);
        scalendar.add(Calendar.DATE, -1);
        date = scalendar.getTime();
        return date;
    }

    /**
     * Get the different day between tow date.
     * 
     * @param fromDate format must be "yyyy-MM-dd"
     * @param toDate format must be "yyyy-MM-dd"
     * @return
     * @throws ParseException
     */
    public static long getDistinctDay(String fromDate, String toDate)
            throws ParseException
    {
        SimpleDateFormat d = new SimpleDateFormat("yyyy-MM-dd");
        long dayCount = 0;
        Date d1 = d.parse(fromDate);
        Date d2 = d.parse(toDate);

        dayCount = (d2.getTime() - d1.getTime()) / (24 * 60 * 60 * 1000);
        return dayCount;
    }

    /**
     *Get the Distinct day between tow date.
     * 
     * @param fromDate
     * @param toDate
     * @return
     * @throws ParseException
     */
    public static long getDistinctDay(Date fromDate, Date toDate)
            throws ParseException
    {
        long dayCount = 0;

        dayCount = (toDate.getTime() - fromDate.getTime())
                / (24 * 60 * 60 * 1000);
        return dayCount;
    }
    
   
    //tank append
    
    /**
     * Checkstyle rule: utility classes should not have public constructor
     */
    private DateUtil() {
    }

    /**
     * Return default datePattern (MM/dd/yyyy)
     * @return a string representing the date pattern on the UI
     */
    public static String getDatePattern() {
        Locale locale = Locale.getDefault();
        String defaultDatePattern = "MM/dd/yyyy";
        try {
            //defaultDatePattern = ResourceBundle.getBundle(Constants.BUNDLE_KEY, locale).getString("date.format");
        } catch (MissingResourceException mse) {
            defaultDatePattern = "MM/dd/yyyy";
        }

        return defaultDatePattern;
    }

    public static String getDateTimePattern() {
        return DateUtil.getDatePattern() + " HH:mm:ss.S";
    }

    /**
     * This method attempts to convert an Oracle-formatted date
     * in the form dd-MMM-yyyy to mm/dd/yyyy.
     *
     * @param aDate date from database as a string
     * @return formatted string for the ui
     */
    public static String getDate(Date aDate) {
        SimpleDateFormat df;
        String returnValue = "";

        if (aDate != null) {
            df = new SimpleDateFormat(getDatePattern());
            returnValue = df.format(aDate);
        }

        return (returnValue);
    }

    /**
     * This method generates a string representation of a date/time
     * in the format you specify on input
     *
     * @param aMask the date pattern the string is in
     * @param strDate a string representation of a date
     * @return a converted Date object
     * @see java.text.SimpleDateFormat
     * @throws ParseException when String doesn't match the expected format
     */
    public static Date convertStringToDate(String aMask, String strDate)
      throws ParseException {
        SimpleDateFormat df;
        Date date;
        df = new SimpleDateFormat(aMask);

        if (log.isDebugEnabled()) {
            log.debug("converting '" + strDate + "' to date with mask '" + aMask + "'");
        }

        try {
            date = df.parse(strDate);
        } catch (ParseException pe) {
            //log.error("ParseException: " + pe);
            throw new ParseException(pe.getMessage(), pe.getErrorOffset());
        }

        return (date);
    }

    /**
     * This method returns the current date time in the format:
     * MM/dd/yyyy HH:MM a
     *
     * @param theTime the current time
     * @return the current date/time
     */
    public static String getTimeNow(Date theTime) {
        return getDateTime(TIME_PATTERN, theTime);
    }

    /**
     * This method returns the current date in the format: MM/dd/yyyy
     * 
     * @return the current date
     * @throws ParseException when String doesn't match the expected format
     */
    public static Calendar getToday() throws ParseException {
        Date today = new Date();
        SimpleDateFormat df = new SimpleDateFormat(getDatePattern());

        // This seems like quite a hack (date -> string -> date),
        // but it works ;-)
        String todayAsString = df.format(today);
        Calendar cal = new GregorianCalendar();
        cal.setTime(convertStringToDate(todayAsString));

        return cal;
    }

    /**
     * This method generates a string representation of a date's date/time
     * in the format you specify on input
     *
     * @param aMask the date pattern the string is in
     * @param aDate a date object
     * @return a formatted string representation of the date
     * 
     * @see java.text.SimpleDateFormat
     */
    public static String getDateTime(String aMask, Date aDate) {
        SimpleDateFormat df = null;
        String returnValue = "";

        if (aDate == null) {
            log.error("aDate is null!");
        } else {
            df = new SimpleDateFormat(aMask);
            returnValue = df.format(aDate);
        }

        return (returnValue);
    }

    /**
     * This method generates a string representation of a date based
     * on the System Property 'dateFormat'
     * in the format you specify on input
     * 
     * @param aDate A date to convert
     * @return a string representation of the date
     */
    public static String convertDateToString(Date aDate) {
        return getDateTime(getDatePattern(), aDate);
    }

    /**
     * This method converts a String to a date using the datePattern
     * 
     * @param strDate the date to convert (in format MM/dd/yyyy)
     * @return a date object
     * @throws ParseException when String doesn't match the expected format
     */
    public static Date convertStringToDate(String strDate)
      throws ParseException {
        Date aDate = null;

        try {
            if (log.isDebugEnabled()) {
                log.debug("converting date with pattern: " + getDatePattern());
            }

            aDate = convertStringToDate(getDatePattern(), strDate);
        } catch (ParseException pe) {
            log.error("Could not convert '" + strDate + "' to a date, throwing exception");
            pe.printStackTrace();
            throw new ParseException(pe.getMessage(),
                                     pe.getErrorOffset());
        }

        return aDate;
    }
}
